using System.Collections.Generic;
using FlexiCommerce.Components;

namespace FlexiCommerce.Collections
{
	/// <summary>
	/// Navigates a graph of content item nodes.
	/// </summary>
    public class ItemHierarchyNavigator : IHierarchyNavigator<HierarchicalPersistenceItem>
    {
        private readonly HierarchyNode<HierarchicalPersistenceItem> currentNode = null;

        public ItemHierarchyNavigator(HierarchyNode<HierarchicalPersistenceItem> currentNode)
        {
            this.currentNode = currentNode;
        }

        public ItemHierarchyNavigator(HierarchyBuilder builder, params ItemFilter[] filters)
        {
            currentNode = builder.Build(filters);
        }

        public ItemHierarchyNavigator(HierarchyBuilder builder)
        {
            currentNode = builder.Build();
        }

        public HierarchyNode<HierarchicalPersistenceItem> CurrentNode
        {
            get { return currentNode; }
        }

        public ItemHierarchyNavigator GetRootHierarchy()
        {
            return new ItemHierarchyNavigator(GetRootNode());
        }

        public HierarchyNode<HierarchicalPersistenceItem> GetRootNode()
        {
            HierarchyNode<HierarchicalPersistenceItem> last = currentNode;
            while (last.Parent != null)
                last = last.Parent;
            return last;
        }

        public IEnumerable<HierarchicalPersistenceItem> EnumerateAllItems()
        {
            HierarchyNode<HierarchicalPersistenceItem> rootNode = GetRootNode();
            return EnumerateItemsRecursive(rootNode);
        }

        public IEnumerable<HierarchicalPersistenceItem> EnumerateChildItems()
        {
            return EnumerateItemsRecursive(currentNode);
        }

        protected virtual IEnumerable<HierarchicalPersistenceItem> EnumerateItemsRecursive(HierarchyNode<HierarchicalPersistenceItem> node)
        {
            yield return node.Current;
            foreach (HierarchyNode<HierarchicalPersistenceItem> childNode in node.Children)
            {
                foreach (HierarchicalPersistenceItem childItem in EnumerateItemsRecursive(childNode))
                {
                    yield return childItem;
                }
            }
        }

        #region IHierarchyItem<HierarchalPersistenceItem> Members

        public IHierarchyNavigator<HierarchicalPersistenceItem> Parent
        {
            get
            {
                if (currentNode.Parent != null)
                    return new ItemHierarchyNavigator(currentNode.Parent);
                else
                    return null;
            }
        }

        public IEnumerable<IHierarchyNavigator<HierarchicalPersistenceItem>> Children
        {
            get
            {
                foreach (HierarchyNode<HierarchicalPersistenceItem> childNode in currentNode.Children)
                {
                    yield return new ItemHierarchyNavigator(childNode);
                }
            }
        }

        public HierarchicalPersistenceItem Current
        {
            get { return currentNode.Current; }
        }

        public bool HasChildren
        {
            get { return currentNode.Children.Count > 0; }
        }

        #endregion
    }
}